﻿using lw;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

namespace XiaoYou.Game.Script.SnqxExilium.Player
{
    public class Lewan
    {
        #region 私有属性

        /// <summary>
        /// 声明乐玩插件
        /// </summary>
        public lwsoft _lw { get; private set; }

        #endregion

        #region 公有属性

        public Action<string> Log { get; set; }

        /// <summary>
        /// 横向坐标
        /// </summary>
        public int GetX
        {
            get { return this._lw.GetX(); }
        }
        /// <summary>
        /// 纵向坐标
        /// </summary>
        public int GetY
        {
            get { return this._lw.GetY(); }
        }

        /// <summary>
        /// 获取当前乐玩插件的版本号
        /// </summary>
        public string GetVer
        {
            get { return this._lw.ver(); }
        }

        /// <summary>
        /// 乐玩插件的全局路径
        /// </summary>
        public string Path
        {
            get { return this._lw.GetPath(); }
            set { this._lw.SetPath(value); }
        }

        public LewanResult LewanResult { get; set; } = new LewanResult();

        /// <summary>
        /// 设置鼠标移动后的等待时间，时间到达之后才进行后面的操作
        /// </summary>
        public int MoveWait { get; set; } = 1500;

        #endregion

        #region 构造函数

        /// <summary>
        /// 构造函数
        /// </summary>
        public Lewan()
        {
            this._lw = new lwsoft();
        }

        /// <summary>
        /// 构造函数
        /// </summary>
        /// <param name="path">全局路径</param>
        public Lewan(string path)
        {
            this._lw = new lwsoft();

            this._lw.SetPath(path);
        }

        /// <summary>
        /// 构造函数
        /// </summary>
        /// <param name="path">全局路径</param>
        /// <param name="file">字库文件名</param>
        public Lewan(string path, params string[] file)
        {
            this._lw = new lwsoft();

            this._lw.SetPath(path);

            for (int i = 0; i < file.Length; i++)
            {
                this._lw.SetDict(i, file[i]);
            }
        }

        public void SetPath(string path)
        {
            this._lw.SetPath(path);
        }

        public void SetDic(params string[] file)
        {
            for (int i = 0; i < file.Length; i++)
            {
                this._lw.SetDict(i, file[i]);
            }
        }

        #endregion

        #region 乐玩函数封装，非Bug情况下禁止修改当前块内的代码

        #region 后台设置

        /// <summary>
        /// 乐玩插件绑定窗口
        /// </summary>
        /// <param name="hwnd">指定的窗口句柄，-1表示绑定桌面窗口</param>
        /// <param name="display">屏幕颜色获取方式</param>
        /// <param name="mouse">鼠标仿真模式</param>
        /// <param name="keypad">键盘仿真模式</param>
        /// <param name="added">附加信息</param>
        /// <param name="mode">模式</param>
        /// <returns></returns>
        public LewanResult BindWindow(int hwnd, Display display = Display.opengl, Mouse mouse = Mouse.windows, Keypad keypad = Keypad.windows, Added added = Added.normal, Mode mode = Mode.normal)
        {
            LewanResult.Ret = this._lw.BindWindow(hwnd, (int)display, (int)mouse, (int)keypad, (int)added, (int)mode);
            return LewanResult;
        }

        /// <summary>
        /// 解除乐玩插件对窗口的绑定
        /// </summary>
        /// <returns></returns>
        public LewanResult UnBindWindow()
        {
            LewanResult.Ret = _lw.UnBindWindow();

            return LewanResult;
        }

        /// <summary>
        /// 强制解除绑定窗口,并释放系统资源
        /// </summary>
        /// <param name="hwnd">需要强制解除绑定的窗口句柄</param>
        /// <returns></returns>
        public LewanResult ForceUnBindWindow(int hwnd)
        {
            LewanResult.Ret = _lw.ForceUnBindWindow(hwnd);

            return LewanResult;
        }

        /// <summary>
        /// 判断指定的区域，在指定的时间内(秒),图像数据是否一直不变.(卡屏).
        /// </summary>
        /// <param name="x1">区域的左上X坐标</param>
        /// <param name="y1">区域的左上Y坐标</param>
        /// <param name="x2">区域的右下X坐标</param>
        /// <param name="y2">区域的右下Y坐标</param>
        /// <param name="time">需要等待的时间,时间单位由timeFlag参数决定</param>
        /// <param name="sim">相似度,取值范围0.1-1.0</param>
        /// <param name="timeFlag">时间单位0＝timeout设置的时间为秒，1＝timeout设置的时间为毫秒</param>
        /// <returns></returns>
        public LewanResult IsDisplayDead(int x1, int y1, int x2, int y2, int time = 5, float sim = 1, int timeFlag = 0)
        {
            LewanResult.Ret = this._lw.IsDisplayDead(x1, y1, x2, y2, time, sim, timeFlag);
            return LewanResult;
        }

        /// <summary>
        /// 移动指定窗口到指定位置
        /// </summary>
        /// <param name="hwnd">指定的窗口句柄</param>
        /// <param name="x">X坐标</param>
        /// <param name="y">Y坐标</param>
        /// <param name="width">新的窗口宽度，为0表示不改变宽度</param>
        /// <param name="height">新的窗口高度，为0表示不改变高度</param>
        /// <param name="wait">移动后的等待时间</param>
        /// <returns></returns>
        public LewanResult MoveWindow(int hwnd, int x, int y, int width = 0, int height = 0, int wait = 0)
        {
            LewanResult.Ret = this._lw.MoveWindow(hwnd, x, y, width, height);

            if (LewanResult.Ret == 1 && wait > 0) { this._lw.delay(wait); }//执行等待操作

            return LewanResult;
        }

        /// <summary>
        /// 延时指定范围内随机毫秒,过程中不阻塞UI操作,不占用CPU. 
        /// </summary>
        /// <param name="wait">等待毫秒数</param>
        /// <returns></returns>
        public LewanResult Delay(int wait)
        {
            LewanResult.Ret = this._lw.delay(wait);
            return LewanResult;
        }

        /// <summary>
        /// 获取一个指定范围内的随机数值
        /// </summary>
        /// <param name="min">欲取随机数的最小值，可以是负数</param>
        /// <param name="max">欲取随机数的最大值，参数必须大于前一个参数</param>
        /// <returns>返回随机数</returns>
        public int GetRnd(int min, int max)
        {
            return this._lw.GetRnd(min, max);
        }

        #endregion

        #region 找图

        /// <summary>
        /// 查找指定区域内的图片,位图必须是24位色格式,支持透明色,当图像上下左右4个顶点的颜色一样时,则这个颜色将作为透明色处理.
        /// 这个函数可以查找多个图片,找到其中任何一张就返回.本函数会设置x,y,idx.
        /// </summary>
        /// <param name="x1">区域的左上X坐标</param>
        /// <param name="y1">区域的左上Y坐标</param>
        /// <param name="x2">区域的右下X坐标</param>
        /// <param name="y2">区域的右下Y坐标</param>
        /// <param name="pic_name">图片名，或者图像数据缓冲区（十进制）,可以是多个图片</param>
        /// <param name="delta_color">颜色色偏比如"203040" 表示RGB的色偏分别是20 30 40 (这里是16进制表示).</param>
        /// <param name="sim">相似度,取值范围0.1-1.0.</param>
        /// <param name="dir">查找方向 0: 从左到右,从上到下 1: 从左到右,从下到上 2: 从右到左,从上到下 3: 从右到左, 从下到上</param>
        /// <param name="timeout">超时，单位为毫秒，如果小于等于0则找一次就返回，否一直找，直到找到或者超时为止</param>
        /// <param name="ischick">找到以后是否点击 1＝找到后点击，0＝找到后并不点击</param>
        /// <param name="chickdex">点击偏移X，如果要点击，相对于找到的点的X坐标偏移多少点击</param>
        /// <param name="chickdey">点击偏移Y，如果要点击，相对于找到的点的Y坐标偏移多少点击</param>
        /// <param name="chickdelay">点击延时，如果要点击，找到后等多久单击，单位为毫秒</param>
        /// <param name="wait">找到图片后的等待时间</param>
        /// <returns></returns>
        public LewanResult FindPic(int x1, int y1, int x2, int y2, string pic_name, string color = "000000", float sim = 0.95f, int dir = 0, int timeout = 0, int ischick = 0, int chickdex = 0, int chickdey = 0, int chickdelay = 0, int wait = 0)
        {
            if (pic_name.IndexOf("*") > -1)
            {

                var pic_name1 = string.Join("|", Directory.GetFiles(_lw.GetPath(), pic_name));
                pic_name = pic_name1.Replace($"{_lw.GetPath()}", "");
            }

            LewanResult.Ret = this._lw.FindPic(x1, y1, x2, y2, pic_name, color, sim, dir, timeout, ischick, chickdex, chickdey, chickdelay);

            if (LewanResult.Ret == 1 && wait > 0) { this._lw.delay(wait); }//执行等待操作

            return LewanResult;
        }

        public string GetFindedPicName()
        {
            return _lw.GetFindedPicName();
        }

        /// <summary>
        /// 查找指定区域内的图片并点击,位图必须是24位色格式,支持透明色,当图像上下左右4个顶点的颜色一样时,则这个颜色将作为透明色处理.
        /// 备注：如果
        /// </summary>
        /// <param name="x1">区域的左上X坐标</param>
        /// <param name="y1">区域的左上Y坐标</param>
        /// <param name="x2">区域的右下X坐标</param>
        /// <param name="y2">区域的右下Y坐标</param>
        /// <param name="pic_name">图片名，或者图像数据缓冲区（十进制）,可以是多个图片</param>
        /// <param name="sim">相似度,取值范围0.1-1.0.</param>
        /// <param name="wait">找到图片后的等待时间</param>
        /// <param name="cx1">点击区域的左上X坐标</param>
        /// <param name="cy1">点击区域的左上Y坐标</param>
        /// <param name="cx2">点击区域的右下X坐标</param>
        /// <param name="cy2">点击区域的右下Y坐标</param>
        /// <param name="cwait">点击后的等待时间</param>
        /// <returns></returns>
        public LewanResult FindPicMoveToClick(int x1, int y1, int x2, int y2, string pic_name, int cx1 = -1, int cy1 = -1, int cx2 = -1, int cy2 = -1, float sim = 0.95f, int wait = 0, int cwait = 0, int timeout = 0)
        {

            if (pic_name.IndexOf("*") > -1)
            {

                var pic_name1 = string.Join("|", Directory.GetFiles(_lw.GetPath(), pic_name));
                pic_name = pic_name1.Replace($"{_lw.GetPath()}", "");
            }
            LewanResult.Ret = 0;
            int c = 0;
            //搜索图片是否存在，找到返回1，没有找到返回0
            while(LewanResult.Ret==0 && c<10)
            {
                LewanResult.Ret = this._lw.FindPic(x1, y1, x2, y2, pic_name, sim: sim, timeout: timeout);
                c++;
            }
          

            pic_name = GetFindedPicName();



            if (LewanResult.Ret == 1 && cx1 != -1 && cy1 != -1)
            {
                Log?.Invoke(pic_name);
                if (wait > 0) { this._lw.delay(wait); }//执行等待操作

                // 执行移动并点击
                LewanResult.Ret += this.MoveToClick(x1, y1, x2, y2, cx1, cy1, cx2, cy2, cwait); // 成功返回1，失败返回0
            }
            else if (LewanResult.Ret == 1)
            {
                if (wait > 0) { this._lw.delay(wait); }//执行等待操作
                Log?.Invoke(pic_name);
                //var findPicEx = this.FindPicEx(x1, y1, x2, y2, pic_name, sim: sim);
                cx1 = _lw.GetX();
                cy2 = _lw.GetY();
                LewanResult.Ret += this._lw.FindPic(x1, y1, x2, y2, pic_name, sim: sim, timeout: timeout, ischick: 1, dx: cx2, dy: cy2);
            }
            return LewanResult;

        }

        /// <summary>
        /// 查找指定区域内的图片,位图必须是24位色格式,支持透明色,当图像上下左右4个顶点的颜色一样时,则这个颜色将作为透明色处理.
        /// 这个函数可以查找多个图片,并且返回所有找到的图像的坐标.
        /// </summary>
        /// <param name="x1">区域的左上X坐标</param>
        /// <param name="y1">区域的左上Y坐标</param>
        /// <param name="x2">区域的右下X坐标</param>
        /// <param name="y2">区域的右下Y坐标</param>
        /// <param name="pic_name">图片名，或者图像数据缓冲区（十进制）,可以是多个图片</param>
        /// <param name="delta_color">颜色色偏比如"203040" 表示RGB的色偏分别是20 30 40 (这里是16进制表示).</param>
        /// <param name="sim">相似度,取值范围0.1-1.0.</param>
        /// <param name="wait">找到图片后的等待时间</param>
        /// <param name="dir">查找方向 0: 从左到右,从上到下 1: 从左到右,从下到上 2: 从右到左,从上到下 3: 从右到左, 从下到上</param>
        /// <returns></returns>
        public List<ExResult> FindPicEx(int x1, int y1, int x2, int y2, string pic_name, string color = "000000", float sim = 0.95f, int wait = 0, int dir = 0)
        {
            if (pic_name.IndexOf("*") > -1)
            {
                pic_name = _lw.MatchPicName(pic_name);
            }

            string result = this._lw.FindPicEx(x1, y1, x2, y2, pic_name, color, sim, dir);

            _lw.delay(wait);

            if (result != null && result.Length > 0)
            {
                List<ExResult> list = new List<ExResult>();

                var a = result.Split('|');

                foreach (var item in a)
                {
                    var b = item.Split(',');
                    list.Add(new ExResult()
                    {
                        Id = Convert.ToInt32(b[0]),
                        x = Convert.ToInt32(b[1]),
                        y = Convert.ToInt32(b[2]),
                    });
                }

                return list;
            }

            return null;
        }

        #endregion

        #region 找色

        /// <summary>
        /// 查找指定区域内的颜色,颜色格式"RRGGBB-DRDGDB",注意,和按键的颜色格式相反 本函数会设置x,y,idx.
        /// </summary>
        /// <param name="x1">区域的左上X坐标</param>
        /// <param name="y1">区域的左上Y坐标</param>
        /// <param name="x2">区域的右下X坐标</param>
        /// <param name="y2">区域的右下Y坐标</param>
        /// <param name="color">颜色 格式为"RRGGBB-DRDGDB".注意，这里只支持RGB颜色.</param>
        /// <param name="sim">相似度,取值范围0.1-1.0</param>
        /// <param name="dir">查找方向 0: 从左到右,从上到下 1: 从左到右,从下到上 2: 从右到左,从上到下 3: 从右到左,从下到上 4：从中心往外查找 5: 从上到下,从左到右 6: 从上到下,从右到左 7: 从下到上,从左到右 8: 从下到上,从右到左</param>
        /// <param name="timeout">查找超时,单位为毫秒,为0则只找一次,否则一直找,直到找到或者超时为止.</param>
        /// <param name="ischick">如果找到是否点击,0=找到不点击;1=如果找到了就点击.</param>
        /// <param name="chickdex">点击偏移X，如果要点击，相对于找到的点的X坐标偏移多少点击</param>
        /// <param name="chickdey">点击偏移Y，如果要点击，相对于找到的点的Y坐标偏移多少点击</param>
        /// <param name="chickdelay">点击延时，如果要点击，找到后等多久单击，单位为毫秒.</param>
        /// <param name="wait">找到色块后的等待时间</param>
        /// <returns></returns>
        public LewanResult FindColor(int x1, int y1, int x2, int y2, string color, float sim = 0.95f, int dir = 0, int timeout = 0, int ischick = 0, int chickdex = 0, int chickdey = 0, int chickdelay = 0, int wait = 0)
        {
            //搜索色块是否存在，找到返回1，没有找到返回0
            LewanResult.Ret = this._lw.FindColor(x1, y1, x2, y2, color, sim, dir, timeout, ischick, chickdex, chickdey, chickdelay);

            if (LewanResult.Ret == 1 && wait > 0) { this._lw.delay(wait); }//执行等待操作

            return LewanResult;
        }

        /// <summary>
        /// 查找指定区域内的颜色并点击,颜色格式"RRGGBB-DRDGDB",注意,和按键的颜色格式相反 本函数会设置x,y,idx.
        /// </summary>
        /// <param name="x1">区域的左上X坐标</param>
        /// <param name="y1">区域的左上Y坐标</param>
        /// <param name="x2">区域的右下X坐标</param>
        /// <param name="y2">区域的右下Y坐标</param>
        /// <param name="color">颜色 格式为"RRGGBB-DRDGDB".注意，这里只支持RGB颜色.</param>
        /// <param name="sim">相似度,取值范围0.1-1.0.</param>
        /// <param name="wait">找到色块后的等待时间</param>
        /// <param name="cx1">点击区域的左上X坐标</param>
        /// <param name="cy1">点击区域的左上Y坐标</param>
        /// <param name="cx2">点击区域的右下X坐标</param>
        /// <param name="cy2">点击区域的右下Y坐标</param>
        /// <param name="cwait">点击后的等待时间</param>
        /// <returns></returns>
        public LewanResult FindColorMoveToClick(int x1, int y1, int x2, int y2, string color, float sim = 0.95f, int wait = 0, int cx1 = -1, int cy1 = -1, int cx2 = -1, int cy2 = -1, int cwait = 0)
        {
            //搜索色块是否存在，找到返回1，没有找到返回0
            LewanResult.Ret = this._lw.FindColor(x1, y1, x2, y2, color, sim: sim);

            if (LewanResult.Ret == 1)
            {
                if (wait > 0) { this._lw.delay(wait); }//执行等待操作

                LewanResult.Ret = 0;
                // 执行移动并点击
                LewanResult.Ret += this.MoveToClick(x1, y1, x2, y2, cx1, cy1, cx2, cy2, cwait); // 成功返回1，失败返回0
            }

            return LewanResult;
        }

        #endregion

        #region 文字识别

        /// <summary>
        /// 识别屏幕范围(x1,y1,x2,y2)内符合color_format的字符串,并且相似度为sim,sim取值范围(0.1-1.0),
        /// 这个值越大越精确,越大速度越快,越小速度越慢,请斟酌使用!
        /// </summary>
        /// <param name="x1">区域的左上X坐标</param>
        /// <param name="y1">区域的左上Y坐标</param>
        /// <param name="x2">区域的右下X坐标</param>
        /// <param name="y2">区域的右下Y坐标</param>
        /// <param name="color">颜色格式串,有两种格式：1，直接写RGB色加-RGB色偏  2，#后面加数值</param>
        /// <param name="sim">相似度,取值范围0.1-1.0</param>
        /// <param name="wait">找到文字后的等待时间</param>
        /// <param name="linesign">换行标志,表示如果碰到换行</param>
        /// <param name="isbackcolor">是否采用背景色识字</param>
        /// <param name="index">字库编号(0-9)</param>
        /// <returns></returns>
        public string Ocr(int x1, int y1, int x2, int y2, string color, float sim = 0.95f, int wait = 0, string linesign = "", int isbackcolor = 0, int index = 0)
        {
            //切换字库
            int flag = this._lw.UseDict(index);

            string result = string.Empty;

            if (flag == 1)
            {
                result = this._lw.Ocr(x1, y1, x2, y2, color, sim, linesign, isbackcolor);

                if (wait > 0) { this._lw.delay(wait); }//执行等待操作
            }

            return result;
        }

        /// <summary>
        /// 在屏幕范围(x1,y1,x2,y2)内,查找string(可以是任意个字符串的组合),并返回符合color_format的坐标位置,相似度sim同Ocr接口描述. 此方法会设置　x,y,idx
        /// 备注：此函数的原理是先Ocr识别，然后再查找。所以速度比FindStrFast要慢，尤其是在字库很大时.
        /// 一般字库字符数量小于100左右，用FindStr要快一些,否则用FindStrFast.
        /// </summary>
        /// <param name="x1">区域的左上X坐标</param>
        /// <param name="y1">区域的左上Y坐标</param>
        /// <param name="x2">区域的右下X坐标</param>
        /// <param name="y2">区域的右下Y坐标</param>
        /// <param name="str">待查找的字符串,可以是字符串组合</param>
        /// <param name="color_format">颜色格式串,有两种格式：1，直接写RGB色加-RGB色偏  2，#后面加数值</param>
        /// <param name="sim">相似度,取值范围0.1-1.0</param>
        /// <param name="wait">找到文字后的等待时间</param>
        /// <param name="isbackcolor">是否背景色,为1表示color_format 所提供的颜色为背景色,否则表示提供的为文字颜色</param>
        /// <param name="index">字库编号(0-9)</param>
        /// <returns></returns>
        public LewanResult FindStr(int x1, int y1, int x2, int y2, string str, string color, float sim = 0.95f, int wait = 0, int isbackcolor = 0, int index = 0)
        {
            //切换字库
            LewanResult.Ret = this._lw.UseDict(index);

            if (LewanResult.Ret == 1)
            {
                LewanResult.Ret += this._lw.FindStr(x1, y1, x2, y2, str, color, sim, isbackcolor);

                if (LewanResult.Ret == 2 && wait > 0) { this._lw.delay(wait); }//执行等待操作
            }

            return LewanResult;
        }

        /// <summary>
        /// 在屏幕范围(x1,y1,x2,y2)内,查找string(可以是任意个字符串的组合),执行点击并返回符合color_format的坐标位置,相似度sim同Ocr接口描述. 此方法会设置　x,y,idx
        /// 备注：此函数的原理是先Ocr识别，然后再查找。所以速度比FindStrFast要慢，尤其是在字库很大时.
        /// 一般字库字符数量小于100左右，用FindStr要快一些,否则用FindStrFast.
        /// </summary>
        /// <param name="x1">区域的左上X坐标</param>
        /// <param name="y1">区域的左上Y坐标</param>
        /// <param name="x2">区域的右下X坐标</param>
        /// <param name="y2">区域的右下Y坐标</param>
        /// <param name="str">待查找的字符串,可以是字符串组合</param>
        /// <param name="color">颜色格式串,有两种格式：1，直接写RGB色加-RGB色偏  2，#后面加数值</param>
        /// <param name="sim">相似度,取值范围0.1-1.0</param>
        /// <param name="wait">找到文字后的等待时间</param>
        /// <param name="isbackcolor">是否背景色,为1表示color_format 所提供的颜色为背景色,否则表示提供的为文字颜色</param>
        /// <param name="index">字库编号(0-9)</param>
        /// <param name="cx1">点击区域的左上X坐标</param>
        /// <param name="cy1">点击区域的左上Y坐标</param>
        /// <param name="cx2">点击区域的右下X坐标</param>
        /// <param name="cy2">点击区域的右下Y坐标</param>
        /// <param name="cwait">点击后的等待时间</param>
        /// <returns></returns>
        public LewanResult FindStrMoveToClick(int x1, int y1, int x2, int y2, string str, string color, float sim = 0.95f, int wait = 0, int isbackcolor = 0, int index = 0, int cx1 = -1, int cy1 = -1, int cx2 = -1, int cy2 = -1, int cwait = 0)
        {
            //切换字库
            LewanResult.Ret = this._lw.UseDict(index);

            if (LewanResult.Ret == 1)
            {
                LewanResult.Ret += this._lw.FindStr(x1, y1, x2, y2, str, color, sim, isbackcolor);

                if (LewanResult.Ret == 2)
                {
                    if (wait > 0) { this._lw.delay(wait); }//执行等待操作

                    // 执行移动并点击
                    LewanResult.Ret += this.MoveToClick(x1, y1, x2, y2, cx1, cy1, cx2, cy2, cwait); // 成功返回1，失败返回0
                }
            }

            return LewanResult;
        }

        /// <summary>
        /// 在屏幕范围(x1,y1,x2,y2)内,查找string(可以是任意个字符串的组合),并返回符合color_format的坐标位置,相似度sim同Ocr接口描述. 此方法会设置　x,y,idx
        /// 备注：此函数比FindStr要快很多，尤其是在字库很大时，或者模糊识别时，效果非常明显。推荐使用此函数。
        /// 另外由于此函数是只识别待查找的字符，所以可能会有如下情况出现问题。
        /// 比如 字库中有"张和三" 一共3个字符数据，然后待识别区域里是"张和三",如果用FindStr查找"张三"肯定是找不到的，
        /// 但是用FindStrFast却可以找到，因为"和"这个字符没有列入查找计划中。
        /// 所以，在使用此函数时，也要特别注意这一点
        /// </summary>
        /// <param name="x1">区域的左上X坐标</param>
        /// <param name="y1">区域的左上Y坐标</param>
        /// <param name="x2">区域的右下X坐标</param>
        /// <param name="y2">区域的右下Y坐标</param>
        /// <param name="str">待查找的字符串,可以是字符串组合</param>
        /// <param name="color_format">颜色格式串,有两种格式：1，直接写RGB色加-RGB色偏  2，#后面加数值</param>
        /// <param name="sim">相似度,取值范围0.1-1.0</param>
        /// <param name="wait">找到文字后的等待时间</param>
        /// <param name="isbackcolor">是否背景色,为1表示color_format 所提供的颜色为背景色,否则表示提供的为文字颜色</param>
        /// <param name="index">字库编号(0-9)</param>
        /// <returns></returns>
        public LewanResult FindStrFast(int x1, int y1, int x2, int y2, string str, string color, float sim = 0.95f, int wait = 0, int isbackcolor = 0, int index = 0)
        {
            //切换字库
            LewanResult.Ret = this._lw.UseDict(index);

            if (LewanResult.Ret == 1)
            {
                LewanResult.Ret += this._lw.FindStrFast(x1, y1, x2, y2, str, color, sim, isbackcolor);

                if (LewanResult.Ret == 2 && wait > 0) { this._lw.delay(wait); }//执行等待操作
            }

            return LewanResult;
        }

        /// <summary>
        /// 在屏幕范围(x1,y1,x2,y2)内,查找string(可以是任意个字符串的组合),执行点击并返回符合color_format的坐标位置,相似度sim同Ocr接口描述. 此方法会设置　x,y,idx
        /// 备注：此函数比FindStr要快很多，尤其是在字库很大时，或者模糊识别时，效果非常明显。推荐使用此函数。
        /// 另外由于此函数是只识别待查找的字符，所以可能会有如下情况出现问题。
        /// 比如 字库中有"张和三" 一共3个字符数据，然后待识别区域里是"张和三",如果用FindStr查找"张三"肯定是找不到的，
        /// 但是用FindStrFast却可以找到，因为"和"这个字符没有列入查找计划中。
        /// 所以，在使用此函数时，也要特别注意这一点
        /// </summary>
        /// <param name="x1">区域的左上X坐标</param>
        /// <param name="y1">区域的左上Y坐标</param>
        /// <param name="x2">区域的右下X坐标</param>
        /// <param name="y2">区域的右下Y坐标</param>
        /// <param name="str">待查找的字符串,可以是字符串组合</param>
        /// <param name="color_format">颜色格式串,有两种格式：1，直接写RGB色加-RGB色偏  2，#后面加数值</param>
        /// <param name="sim">相似度,取值范围0.1-1.0</param>
        /// <param name="wait">找到文字后的等待时间</param>
        /// <param name="isbackcolor">是否背景色,为1表示color_format 所提供的颜色为背景色,否则表示提供的为文字颜色</param>
        /// <param name="index">字库编号(0-9)</param>
        /// <param name="cx1">点击区域的左上X坐标</param>
        /// <param name="cy1">点击区域的左上Y坐标</param>
        /// <param name="cx2">点击区域的右下X坐标</param>
        /// <param name="cy2">点击区域的右下Y坐标</param>
        /// <param name="cwait">点击后的等待时间</param>
        /// <returns></returns>
        public LewanResult FindStrFastMoveToClick(int x1, int y1, int x2, int y2, string str, string color, float sim = 0.95f, int wait = 0, int isbackcolor = 0, int index = 0, int cx1 = -1, int cy1 = -1, int cx2 = -1, int cy2 = -1, int cwait = 0)
        {
            //切换字库
            LewanResult.Ret = this._lw.UseDict(index);

            if (LewanResult.Success)
            {
                LewanResult.Ret = this._lw.FindStrFast(x1, y1, x2, y2, str, color, sim, isbackcolor);

                if (LewanResult.Success)
                {
                    if (wait > 0) { this._lw.delay(wait); }//执行等待操作

                    // 执行移动并点击
                    LewanResult.Ret = this.MoveToClick(x1, y1, x2, y2, cx1, cy1, cx2, cy2, cwait); // 成功返回1，失败返回0
                }
            }

            return LewanResult;
        }

        #endregion

        #region 鼠标、键盘

        /// <summary>
        /// 按下指定的虚拟键码
        /// </summary>
        /// <param name="vk_code">虚拟按键码</param>
        /// <param name="num">按键次数,默认1次.</param>
        /// <param name="wait">操作成功后的等待时间</param>
        /// <returns></returns>
        public LewanResult KeyPress(int vk_code, int num = 1, int wait = 0)
        {
            LewanResult.Ret = this._lw.KeyPress(vk_code, num);

            if (LewanResult.Success && wait > 0) { this._lw.delay(wait); }//执行等待操作

            return LewanResult;
        }

        /// <summary>
        /// 按下指定的虚拟键码,可以是组合键
        /// </summary>
        /// <param name="vk_code">虚拟按键码</param>
        /// <param name="stateKey">状态键</param>
        /// <param name="num">执行次数,默认1次</param>
        /// <param name="wait">操作成功后的等待时间</param>
        /// <returns></returns>
        public LewanResult KeyPressEx(int vk_code, StateKey stateKey, int num = 2, int wait = 0)
        {
            int result = 0;
            for (int i = 0; i < num; i++)
            {
                result += this._lw.KeyPressEx(vk_code, (int)stateKey);
                this._lw.delay(this.MoveWait);
            }

            if (result == num && wait > 0)
            {
                LewanResult.Ret = 1;
                //执行等待操作
                this._lw.delay(wait);
            }
            else
            {
                LewanResult.Ret = 0;
            }

            return LewanResult;
        }

        /// <summary>
        /// 根据指定的字符串序列，依次按顺序按下其中的字符
        /// 备注：该方法适用于账号密码的输入，只支持标英文大小写字母,数字,和半角字符
        /// </summary>
        /// <param name="key_str">需要按下的字符串序列.</param>
        /// <param name="delay">每按下一个按键，需要延时多久. 单位毫秒.这个值越大，按的速度越慢</param>
        /// <param name="wait">操作成功后的等待时间</param>
        /// <returns></returns>
        public LewanResult KeyPressStr(string key_str, int delay = 50, int wait = 0)
        {
            LewanResult.Ret = this._lw.KeyPressStr(key_str, delay);

            if (LewanResult.Success && wait > 0) { this._lw.delay(wait); }//执行等待操作

            return LewanResult;
        }

        /// <summary>
        /// 向指定窗口发送文本数据
        /// 备注：该方法适用于中文录入
        /// </summary>
        /// <param name="str">发送的文本数据</param>
        /// <param name="mod">方式</param>
        /// <param name="wait">操作成功后的等待时间</param>
        /// <returns></returns>
        public LewanResult SendString(string str, Mod mod = Mod.normal, int wait = 0)
        {
            LewanResult.Ret = this._lw.SendString(str, (int)mod);

            if (LewanResult.Success && wait > 0) { this._lw.delay(wait); }//执行等待操作

            return LewanResult;
        }

        /// <summary>
        /// 按住指定的虚拟键码
        /// </summary>
        /// <param name="vk_code">虚拟按键码</param>
        /// <param name="wait">完成后的等待时间</param>
        /// <returns></returns>
        public bool KeyDown(int vk_code, int wait = 0)
        {
            int result = this._lw.KeyDown(vk_code);

            if (result == 1 && wait > 0) { this._lw.delay(wait); }//执行等待操作

            return result == 1 ? true : false;
        }

        /// <summary>
        /// 弹起指定的虚拟键码
        /// </summary>
        /// <param name="vk_code">虚拟按键码</param>
        /// <param name="wait">完成后的等待时间</param>
        /// <returns></returns>
        public bool KeyUp(int vk_code, int wait = 0)
        {
            int result = this._lw.KeyUp(vk_code);

            if (result == 1 && wait > 0) { this._lw.delay(wait); }//执行等待操作

            return result == 1 ? true : false;
        }


        /// <summary>
        /// 把鼠标移动到目的点(x,y)
        /// </summary>
        /// <param name="x">X坐标</param>
        /// <param name="y">Y坐标</param>
        /// <param name="wait">移动完成后的等待时间</param>
        /// <returns></returns>
        public bool MoveTo(int x, int y, int wait = 500)
        {
            int result = this._lw.MoveTo(x, y);

            if (result == 1 && wait > 0) { this._lw.delay(wait); }//执行等待操作

            return result == 1 ? true : false;
        }

        /// <summary>
        /// 把鼠标移动到目的范围内的任意一点
        /// </summary>
        /// <param name="x1">区域的左上X坐标</param>
        /// <param name="y1">区域的左上Y坐标</param>
        /// <param name="x2">区域的右下X坐标</param>
        /// <param name="y2">区域的右下Y坐标</param>
        /// <param name="wait">移动完成后的等待时间</param>
        /// <returns></returns>
        public bool MoveTo(int x1, int y1, int x2, int y2, int wait = 500)
        {
            int w = x2 - x1; //计算宽度
            int h = y2 - y1; //计算高度

            int result = this._lw.MoveToEx(x1, y1, w, h);

            if (result == 1 && wait > 0) { this._lw.delay(wait); }//执行等待操作

            return result == 1 ? true : false;
        }

        /// <summary>
        /// 把鼠标移动到目的点(x,y),并执行左键点击
        /// </summary>
        /// <param name="x">X坐标</param>
        /// <param name="y">Y坐标</param>
        /// <param name="wait">移动完成后的等待时间</param>
        /// <returns></returns>
        public bool MoveToClick(int x, int y, int wait = 0)
        {
            int result = this._lw.MoveTo(x, y);

            this._lw.delay(this.MoveWait);

            result += this._lw.LeftClick();

            if (result == 2 && wait > 0) { this._lw.delay(wait); }//执行等待操作

            return result == 2 ? true : false;
        }

        /// <summary>
        /// 把鼠标移动到目的范围内的任意一点,并执行左键点击
        /// </summary>
        /// <param name="x1">区域的左上X坐标</param>
        /// <param name="y1">区域的左上Y坐标</param>
        /// <param name="x2">区域的右下X坐标</param>
        /// <param name="y2">区域的右下Y坐标</param>
        /// <param name="wait">移动完成后的等待时间</param>
        /// <returns></returns>
        public LewanResult MoveToClick(int x1, int y1, int x2, int y2, int wait = 0)
        {
            int w = x2 - x1; //计算宽度
            int h = y2 - y1; //计算高度

            LewanResult.Ret = this._lw.MoveToEx(x1, y1, w, h);

            this._lw.delay(this.MoveWait);

            LewanResult.Ret += this._lw.LeftClick();

            if (LewanResult.Ret == 2 && wait > 0)
            {
                LewanResult.Ret = 1;
                this._lw.delay(wait);
            }//执行等待操作

            return LewanResult;
        }

        /// <summary>
        /// 将鼠标移动到指定点位，并执行左键按住操作
        /// </summary>
        /// <param name="x">X坐标</param>
        /// <param name="y">Y坐标</param>
        /// <param name="wait">完成后的等待时间</param>
        /// <returns></returns>
        public bool LeftDown(int x, int y, int wait = 0)
        {
            int result = this._lw.MoveTo(x, y);//移动鼠标到点位

            this._lw.delay(this.MoveWait);

            result += this._lw.LeftDown();

            if (result == 2 && wait > 0) { this._lw.delay(wait); }//执行等待操作

            return result == 2 ? true : false;
        }

        /// <summary>
        /// 将鼠标移动到指定点位，并执行左键弹起操作
        /// </summary>
        /// <param name="x">X坐标</param>
        /// <param name="y">Y坐标</param>
        /// <param name="wait">完成后的等待时间</param>
        /// <returns></returns>
        public bool LeftUp(int x, int y, int wait = 0)
        {
            int result = this._lw.MoveTo(x, y);//移动鼠标到点位

            this._lw.delay(this.MoveWait);

            result += this._lw.LeftUp();

            if (result == 2 && wait > 0) { this._lw.delay(wait); }//执行等待操作

            return result == 2 ? true : false;
        }

        /// <summary>
        /// 滚轮向下滚
        /// </summary>
        /// <param name="x">X坐标</param>
        /// <param name="y">Y坐标</param>
        /// <param name="count">滚动次数</param>
        /// <param name="wait">完成后的等待时间</param>
        /// <returns></returns>
        public bool WheelDown(int x, int y, int count = 1, int wait = 0)
        {
            int result = this._lw.MoveTo(x, y);//移动鼠标到点位

            this._lw.delay(this.MoveWait);

            for (int i = 0; i < count; i++)
            {
                result += this._lw.WheelDown();

                this._lw.delay(400);
            }

            if (result == count && wait > 0) { this._lw.delay(wait); }//执行等待操作

            return result == 0 ? false : true;
        }

        /// <summary>
        /// 滚轮向上滚
        /// </summary>
        /// <param name="x">X坐标</param>
        /// <param name="y">Y坐标</param>
        /// <param name="count">滚动次数</param>
        /// <param name="wait">完成后的等待时间</param>
        /// <returns></returns>
        public bool WheelUp(int x, int y, int count = 1, int wait = 0)
        {
            int result = this._lw.MoveTo(x, y);//移动鼠标到点位

            this._lw.delay(this.MoveWait);

            for (int i = 0; i < count; i++)
            {
                result += this._lw.WheelUp();

                this._lw.delay(400);
            }

            if (result == count && wait > 0) { this._lw.delay(wait); }//执行等待操作

            return result == 0 ? false : true;
        }

        /// <summary>
        /// 执行模拟器的拖拽事件
        /// </summary>
        /// <param name="x1">起始点位的X坐标</param>
        /// <param name="y1">起始点位的Y坐标</param>
        /// <param name="x2">结束点位的X坐标</param>
        /// <param name="y2">结束点位的Y坐标</param>
        /// <param name="mSec">拖动时间毫秒</param>
        /// <param name="wait">完成后的等待时间</param>
        public bool MouseDrag(int x1, int y1, int x2, int y2, int mSec = 500, int wait = 0)
        {
            //ThunderHelper.MouseDrag(index, x1, y1, x2, y2, mSec);

            bool result = false;

            result = this.LeftDown(x1, y1);
            if (mSec > 0) { this._lw.delay(mSec); }
            result = this.LeftUp(x2, y2);

            if (wait > 0) { this._lw.delay(wait); }//执行等待操作

            return result;
        }

        #endregion

        #region 配置文件

        /// <summary>
        /// 指定文本内容写入指定配置项中，如果指定配置文件不存在，将会自动创建。
        /// </summary>
        /// <param name="file">文件名，指定配置文件的名称，通常以.ini作为文件名后缀</param>
        /// <param name="section">节名称，包含欲写入配置项所处节的名称</param>
        /// <param name="key">配置项。包含欲写入配置项所处项目名称</param>
        /// <param name="value">欲写入值</param>
        /// <returns></returns>
        public bool IniWrite(string file, string section, string key, string value)
        {
            int result = this._lw.IniWrite(file, section, key, value);

            return result == 1 ? true : false;
        }

        /// <summary>
        /// 读取指定配置文件中指定项目的文本内容
        /// </summary>
        /// <param name="file">文件名，指定配置文件的名称，通常以.ini作为文件名后缀</param>
        /// <param name="section">节名称，指定欲读入配置项所处节的名称</param>
        /// <param name="key">配置项，指定欲写入配置项所处项目名称</param>
        /// <param name="def">默认文本，指定的条目没有找到时返回的默认值。可空，默认为一个空文本</param>
        /// <returns></returns>
        public string IniRead(string file, string section, string key, string def = "")
        {
            string result = this._lw.IniRead(file, section, key, def);

            return result;
        }

        /// <summary>
        /// 删除指定配置文件中的指定节
        /// </summary>
        /// <param name="file">文件名，指定配置文件的名称，通常以.ini作为文件名后缀</param>
        /// <param name="section">欲删除的节的节名称</param>
        /// <returns></returns>
        public bool IniDeleteSection(string file, string section)
        {
            int result = this._lw.IniDeleteSection(file, section);

            return result == 1 ? true : false;
        }

        /// <summary>
        /// 删除指定配置文件中指定节下的指定配置项
        /// </summary>
        /// <param name="file">文件名，指定配置文件的名称，通常以.ini作为文件名后缀</param>
        /// <param name="section">欲删除配置项所在的节的节名称</param>
        /// <param name="key">欲删除的配置项的名称</param>
        /// <returns></returns>
        public bool IniDeleteKey(string file, string section, string key)
        {
            int result = this._lw.IniDeleteKey(file, section, key);

            return result == 1 ? true : false;
        }

        /// <summary>
        /// 枚举指定配置文件中所有的节的节名称
        /// </summary>
        /// <param name="file">文件名，指定配置文件的名称，通常以.ini作为文件名后缀</param>
        /// <returns></returns>
        public List<string> IniEnumSection(string file)
        {
            string result = this._lw.IniEnumSection(file);

            List<string> list = new List<string>();

            if (!string.IsNullOrWhiteSpace(result))
            {
                string[] arr = result.Split('|');

                foreach (string item in arr)
                {
                    list.Add(item);
                }
            }

            return list;
        }

        /// <summary>
        /// 枚举指定配置文件中指定节下的所有配置项
        /// </summary>
        /// <param name="file">文件名，指定配置文件的名称，通常以.ini作为文件名后缀</param>
        /// <param name="section">欲枚举的配置项所处的节名称</param>
        /// <returns></returns>
        public List<string> IniEnumKey(string file, string section)
        {
            string result = this._lw.IniEnumKey(file, section);

            List<string> list = new List<string>();

            if (!string.IsNullOrWhiteSpace(result))
            {
                string[] arr = result.Split('|');

                foreach (string item in arr)
                {
                    list.Add(item);
                }
            }

            return list;
        }

        #endregion

        #endregion

        #region 私有方法

        /// <summary>
        /// 执行鼠标移动并点击的方法
        /// </summary>
        /// <param name="x1">区域的左上X坐标</param>
        /// <param name="y1">区域的左上Y坐标</param>
        /// <param name="x2">区域的右下X坐标</param>
        /// <param name="y2">区域的右下Y坐标</param>
        /// <param name="cx1">点击区域的左上X坐标</param>
        /// <param name="cy1">点击区域的左上Y坐标</param>
        /// <param name="cx2">点击区域的右下X坐标</param>
        /// <param name="cy2">点击区域的右下Y坐标</param>
        /// <param name="cwait">点击后的等待时间</param>
        /// <returns>成功返回1，失败返回0</returns>
        private int MoveToClick(int x1, int y1, int x2, int y2, int cx1 = -1, int cy1 = -1, int cx2 = -1, int cy2 = -1, int cwait = 0)
        {
            int result = 0;

            //找到文字后执行点击操作
            int w = 0; //定义宽度
            int h = 0; //定义高度

            //找到图片，执行定位点击操作
            if (cx1 == -1 && cy1 == -1 && cx2 == -1 && cy2 == -1) //直接对图片存在点位执行点击操作
            {
                w = x2 - x1; //计算宽度
                h = y2 - y1; //计算高度

                //直接进行点位点击，而不需要随机点位点击
                result += this._lw.MoveToEx(x1, y1, w, h); // 成功返回1，失败返回0
            }
            else if (cx1 != -1 && cy1 != -1 && cx2 == -1 && cy2 == -1) //对指定点位进行点击操作
            {
                result += this._lw.MoveTo(cx1, cy1); // 成功返回1，失败返回0
            }
            else //对指定区域随机生成点位进行点击操作
            {
                w = cx2 - cx1; //计算宽度
                h = cy2 - cy1; //计算高度

                //区域内随机获取点位进行点击
                result += this._lw.MoveToEx(cx1, cy1, w, h); // 成功返回1，失败返回0
            }

            // 执行等待，鼠标移动需要时间，否则直接点击无效
            this._lw.delay(this.MoveWait);

            // 执行点击操作
            result += this._lw.LeftClick(); // 成功返回1，失败返回0

            if (result == 2 && cwait > 0) { this._lw.delay(cwait); }//执行等待操作

            return result == 2 ? 1 : 0;
        }

        #endregion

        #region 兼容方法（兼容之前代码）
        public LewanResult Input(string str, int x1, int y1, int x2, int y2, int wait = 1000, int deay = 50)
        {
            LewanResult = this.MoveToClick(x1, y1, x2, y2, wait);
            LewanResult = LewanResult.Success ? this.KeyPressStr(str, deay, wait) : LewanResult;
            return LewanResult;
        }

        #endregion

    }


    /// <summary>
    /// 扩展方法的返回对象
    /// </summary>
    public class ExResult
    {
        /// <summary>
        /// 序号
        /// </summary>
        public int Id { get; set; }

        /// <summary>
        /// X坐标
        /// </summary>
        public int x { get; set; }

        /// <summary>
        /// Y坐标
        /// </summary>
        public int y { get; set; }
    }

    /// <summary>
    /// 乐玩的枚举参数
    /// </summary>

    /// <summary>
    /// 屏幕颜色获取方式 - BindWindow
    /// </summary>
    public enum Display
    {
        /// <summary>
        /// 正常模式,平常我们用的前台截屏模式
        /// </summary>
        normal = 0,
        /// <summary>
        /// gdi模式,用于窗口采用GDI方式刷新时. 此模式占用CPU较大
        /// </summary>
        gdi = 1,
        /// <summary>
        /// gdi2模式,此模式兼容性较强,但是速度比gdi模式要慢许多,如果gdi模式发现后台不刷新时,可以考虑用gdi2模式
        /// </summary>
        gdi2 = 2,
        /// <summary>
        /// dx2模式,用于窗口采用dx模式刷新,如果dx方式会出现窗口所在进程崩溃的状况,可以考虑采用这种.
        /// 采用这种方式要保证窗口有一部分在屏幕外.vista以上系统不需要移动也可后台.此模式占用CPU较大
        /// </summary>
        dx2 = 3,
        /// <summary>
        /// dx模式,注意此模式需要管理员权限
        /// </summary>
        dx = 4,
        /// <summary>
        /// 用于窗口采用Opengl模式刷新。注意此模式需要管理员权限
        /// </summary>
        opengl = 5
    }

    /// <summary>
    /// 鼠标仿真模式 - BindWindow
    /// </summary>
    public enum Mouse
    {
        /// <summary>
        /// 正常模式,平常我们用的前台鼠标模式
        /// </summary>
        normal = 0,
        /// <summary>
        /// Windows模式,采取模拟windows消息方式 同按键自带后台插件
        /// </summary>
        windows = 1,
        /// <summary>
        /// Windows3模式，采取模拟windows消息方式,可以支持有多个子窗口的窗口后台
        /// </summary>
        windows3 = 2,
        /// <summary>
        /// dx模式,采用模拟dx后台鼠标模式。有些窗口在此模式下绑定时，
        /// 需要先激活窗口再绑定(或者绑定以后激活)，否则可能会出现绑定后鼠标无效的情况注意此模式需要管理员权限
        /// </summary>
        dx = 3,
        /// <summary>
        /// dx2模式,同DX，如果DX无效，可以尝试下这个
        /// </summary>
        dx2 = 4
    }

    /// <summary>
    /// 键盘仿真模式 - BindWindow
    /// </summary>
    public enum Keypad
    {
        /// <summary>
        /// 正常模式,平常我们用的前台键盘模式
        /// </summary>
        normal = 0,
        /// <summary>
        /// Windows模式,采取模拟windows消息方式 同按键的后台插件
        /// </summary>
        windows = 1,
        /// <summary>
        /// Windows3模式,采取模拟windows消息方式 同按键的后台插件，
        /// 如果上一个模式不能正常按组合键，可以尝试此模式
        /// </summary>
        windows3 = 2,
        /// <summary>
        /// dx模式,采用模拟dx后台键盘模式。有些窗口在此模式下绑定时，
        /// 需要先激活窗口再绑定(或者绑定以后激活)，否则可能会出现绑定后键盘无效的情况
        /// </summary>
        dx = 3,
        /// <summary>
        /// dx2模式,同DX，如果DX无效，可以尝试下这个
        /// </summary>
        dx2 = 4
    }

    /// <summary>
    /// 附加信息 - BindWindow
    /// </summary>
    public enum Added
    {
        /// <summary>
        /// 该参数的缺省值
        /// </summary>
        normal = 0,
        /// <summary>
        /// 锁定前台窗口，让目标窗口一直以为自己是前台窗口; 
        /// 注意，部分窗口在此模式下会耗费大量资源慎用
        /// </summary>
        a1 = 1,
        /// <summary>
        /// 锁定窗口激活状态，保持目标窗口一直处于激活状态; 
        /// 注意，部分窗口在此模式下会耗费大量资源慎用
        /// </summary>
        a2 = 2,
        /// <summary>
        /// 锁定鼠标位置，如果鼠标不能正常点击，可以尝试加上这个
        /// </summary>
        a4 = 4,
        /// <summary>
        /// 锁定键盘鼠标按键状态，如果不能正常后台后按键或者鼠标点击，可以尝试加上这个
        /// </summary>
        a8 = 8,
        /// <summary>
        /// 需要取后台鼠标特征码
        /// </summary>
        a16 = 16,
        /// <summary>
        /// 需要用输入法输入文本
        /// </summary>
        a32 = 32,
        /// <summary>
        /// 增强型锁定按键状态(如果ctrl,shift,alt键无效可尝试加上这个。) 
        /// </summary>
        a64 = 64,
        /// <summary>
        /// 增强型降CPU,需要在绑定图像模式不为，dx,opengl,opengl2模式时，仍要降低目标进程的CPU占用
        /// </summary>
        a128 = 128,
        /// <summary>
        /// 增强最小化截图，此模式主要是针对采用DX模式刷新的程序，
        /// 如果DX图色模式可以正常截图，但不能最小化截图，可以尝试加上这个
        /// </summary>
        a256 = 256,
        /// <summary>
        /// 增强鼠标。某些窗口的某些鼠标动作要开启这个才能正常执行
        /// </summary>
        a512 = 512
    }

    /// <summary>
    /// 模式 - BindWindow
    /// </summary>
    public enum Mode
    {
        /// <summary>
        /// 推荐模式此模式比较通用，而且后台效果是最好的，并且会隐藏目标进程中的lw.dll
        /// </summary>
        normal = 0,
        /// <summary>
        /// 如果嫌用模式0绑定慢，或者模式0和模式2会造成目标进程崩溃可以用这个模式，这个模式绑定速度最快
        /// </summary>
        m1 = 1,
        /// <summary>
        /// 同模式0,如果模式0或者模式1绑定失败，可以尝试这个模式
        /// </summary>
        m2 = 2,
        /// <summary>
        /// 如果前几个模式都绑定不了，一定要试试这个（如果绑定不成功，可能要较长时间判断）
        /// </summary>
        m3 = 3,
        /// <summary>
        /// 强力绑定模式，如果前面几个绑不上，一定要试试这个
        /// </summary>
        m4 = 4
    }

    /// <summary>
    /// 方式 - SendString
    /// </summary>
    public enum Mod
    {
        /// <summary>
        /// 控件模式
        /// </summary>
        normal = 0,
        /// <summary>
        /// 模式2
        /// </summary>
        m1 = 1,
        /// <summary>
        /// 输入法模式1
        /// </summary>
        m2 = 2,
        /// <summary>
        /// 输入法模式2　(需要在绑定的时候设置附加信息32)
        /// </summary>
        m3 = 3,
        /// <summary>
        /// 输入法模式3　(需要在绑定的时候设置附加信息32)
        /// </summary>
        m4 = 4
    }

    /// <summary>
    /// 状态键 KeyPressEx
    /// </summary>
    public enum StateKey
    {
        /// <summary>
        /// 无状态键
        /// </summary>
        normal = 0,
        /// <summary>
        /// Alt
        /// </summary>
        Alt = 1,
        /// <summary>
        /// Ctrl
        /// </summary>
        Ctrl = 2,
        /// <summary>
        /// Shift
        /// </summary>
        Shift = 3

    }
}
